#include "kms_file_system_watcher.h"
#include "database/file_system_status.h"
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <QCryptographicHash>
#include <QSqlQuery>
#include <QFileInfo>
#include <QDirIterator>
#include <QDateTime>
#include <QUuid>
#include <thread>

// WatcherInfo 结构定义
// 关闭句柄的回调函数
static void onHandleClose(uv_handle_t* handle) {
    // 句柄已关闭，可以安全删除
    if (handle) {
        uv_fs_event_t* fs_event = reinterpret_cast<uv_fs_event_t*>(handle);
        
        // 删除句柄（此时 data 可能已经无效，所以不访问它）
        delete fs_event;
        
        // 注意：WatcherInfo 的清理由 KmsFileSystemWatcher 负责
        // 在 removeWatcher/removeAllWatchers 中已经删除
    }
}

struct WatcherInfo {
    uv_fs_event_t *handle;
    KmsFileSystemWatcher *watcher;
    QString path;
    bool isDirectory;
    bool closing;  // 标记是否正在关闭
    
    WatcherInfo() : handle(nullptr), watcher(nullptr), isDirectory(false), closing(false) {}
    
    ~WatcherInfo() {
        // 析构函数中不再处理句柄，由 removeWatcher 或 removeAllWatchers 负责
    }
};

KmsFileSystemWatcher::KmsFileSystemWatcher(QObject *parent)
    : QObject(parent)
    , m_loop(nullptr)
    , m_eventLoopThread(nullptr)
    , m_databaseManager(nullptr)
    , m_delayTimer(new QTimer(this))
    , m_stopping(false)
{
    // 设置延迟处理定时器，避免频繁更新
    m_delayTimer->setSingleShot(true);
    m_delayTimer->setInterval(1000); // 1秒延迟
    
    connect(m_delayTimer, &QTimer::timeout, this, &KmsFileSystemWatcher::processDelayedFsActions);

    // 启动 libuv 事件循环
    startEventLoop();

    qDebug() << "FileSystemWatcher 初始化完成";
}

KmsFileSystemWatcher::~KmsFileSystemWatcher()
{
    stopWatching();
    stopEventLoop();
    
    // 清理待处理队列中的内存（使用互斥锁保护）
    {
        QMutexLocker locker(&m_pendingActionsMutex);
        for (FsAction &action : m_pendingActions) {
            if (action.path) {
                delete action.path;
                action.path = nullptr;
            }
        }
        m_pendingActions.clear();
    }
}

void KmsFileSystemWatcher::setDatabaseManager(DatabaseManager *dbManager)
{
    m_databaseManager = dbManager;
    qDebug() << "FileSystemWatcher 设置数据库管理器";
}

void KmsFileSystemWatcher::startWatching(const QString &directoryPath)
{
    qDebug() << "FileSystemWatcher: 请求开始监听目录:" << directoryPath;
    
    if (directoryPath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 目录路径为空，无法开始监听";
        return;
    }

    QString cleanPath = QDir::cleanPath(directoryPath);
    
    // 检查是否已经在监听相同目录
    if (!m_watchedDirectory.isEmpty() && m_watchedDirectory == cleanPath) {
        // 检查是否已经在监听器中
        QMutexLocker locker(&m_watchersMutex);
        if (m_watchers.contains(cleanPath)) {
            qDebug() << "FileSystemWatcher: 目录已在监听中，无需重复设置:" << cleanPath;
            return;
        }
        locker.unlock();
    }

    // 如果目录不同，需要停止之前的监听
    if (!m_watchedDirectory.isEmpty() && m_watchedDirectory != cleanPath) {
        qDebug() << "FileSystemWatcher: 目录已变更，停止之前的监听:" << m_watchedDirectory;
        stopWatching();
    }

    // 检查目录是否存在，不存在则创建
    QDir dir(cleanPath);
    if (!dir.exists()) {
        qDebug() << "FileSystemWatcher: 目录不存在，尝试创建:" << cleanPath;
        if (dir.mkpath(".")) {
            qDebug() << "FileSystemWatcher: 成功创建目录:" << cleanPath;
        } else {
            qDebug() << "FileSystemWatcher: 创建目录失败:" << cleanPath;
            return;
        }
    }

    qDebug() << "FileSystemWatcher: 目录存在，开始设置监听";

    m_watchedDirectory = cleanPath;
    qDebug() << "FileSystemWatcher: 设置监听目录为:" << m_watchedDirectory;

    // 确保事件循环已启动
    if (!m_loop) {
        startEventLoop();
    }

    // 直接添加主目录到监听器（不需要先移除所有监听器）
    if (addWatcher(m_watchedDirectory, true)) {
        qDebug() << "FileSystemWatcher: 成功开始监听主目录:" << m_watchedDirectory;
    } else {
        qDebug() << "FileSystemWatcher: 无法监听主目录:" << m_watchedDirectory;
        return;
    }

    // 使用 UV_FS_EVENT_RECURSIVE 标志后，只需监听根目录即可
    // libuv 会自动递归监听所有子目录，无需手动递归添加
    qDebug() << "FileSystemWatcher: 使用递归标志，无需手动递归添加子目录";
    
    qDebug() << "FileSystemWatcher: 监听设置完成";
}

void KmsFileSystemWatcher::stopWatching()
{
    qDebug() << "FileSystemWatcher: 请求停止监听";
    
    if (!m_watchedDirectory.isEmpty()) {
        qDebug() << "FileSystemWatcher: 当前监听目录:" << m_watchedDirectory;
        
        // 移除所有监听器
        removeAllWatchers();
        
        qDebug() << "FileSystemWatcher: 停止监听目录:" << m_watchedDirectory;
        m_watchedDirectory.clear();
    } else {
        qDebug() << "FileSystemWatcher: 没有正在监听的目录";
    }
}

QString KmsFileSystemWatcher::getWatchedDirectory() const
{
    return m_watchedDirectory;
}

bool KmsFileSystemWatcher::isFileInWatchedDirectory(const QString &filePath) const
{
    if (m_watchedDirectory.isEmpty() || filePath.isEmpty()) {
        return false;
    }
    
    QString cleanFilePath = QDir::cleanPath(filePath);
    return cleanFilePath.startsWith(m_watchedDirectory);
}

void KmsFileSystemWatcher::handleDirAddedEvent(const QString &path)
{
    qDebug() << "FileSystemWatcher: handleDirAddedEvent 被调用:" << path;
    
    // 检查目录是否存在且是目录
    QFileInfo dirInfo(path);
    if (!dirInfo.exists() || !dirInfo.isDir()) {
        qDebug() << "FileSystemWatcher: 目录不存在或不是目录，跳过处理:" << path;
        return;
    }
    
    // 检查数据库管理器是否可用
    if (!m_databaseManager) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空，无法处理目录事件";
        return;
    }
    
    // 获取相对路径
    QString relativePath = getRelativeFilePath(path);
    if (relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 相对路径为空，无法处理目录事件";
        return;
    }
    
    // 规范化相对路径（统一使用正斜杠，去掉开头的斜杠）
    QString normalizedRelativePath = relativePath;
    normalizedRelativePath.replace('\\', '/');
    if (normalizedRelativePath.startsWith('/')) {
        normalizedRelativePath = normalizedRelativePath.mid(1);
    }
    
    // 查询 kms_folder 表（通过 path 匹配）
    QString folderPath = "/" + normalizedRelativePath;
    KmsFolder folder = m_databaseManager->queryFolderByExactPath(folderPath);
    
    if (!folder.id.isEmpty()) {
        // 存在记录，不做处理
        qDebug() << "FileSystemWatcher: 目录已存在记录，不做处理，目录路径:" << folderPath;
        return;
    }
    
    // 不存在记录，插入新记录
    qDebug() << "FileSystemWatcher: 检测到新目录创建，准备插入记录:" << path;
    
    // 从相对路径中提取父文件夹路径和目录名
    int lastSlashIndex = normalizedRelativePath.lastIndexOf('/');
    QString parentFolderPath;
    QString dirName;
    
    if (lastSlashIndex >= 0) {
        parentFolderPath = normalizedRelativePath.left(lastSlashIndex);
        dirName = normalizedRelativePath.mid(lastSlashIndex + 1);
    } else {
        // 目录在根目录下
        parentFolderPath = QString();
        dirName = normalizedRelativePath;
    }
    
    // 查找父文件夹信息
    KmsFolder parentFolder;
    if (!parentFolderPath.isEmpty()) {
        parentFolder = m_databaseManager->queryFolderByExactPath("/" + parentFolderPath);
    } else {
        // 如果父文件夹路径为空，说明是根目录下的文件夹，需要查找根文件夹
        // 根文件夹的 path 通常是 "/" 或者网盘名称
        // 这里尝试查找根文件夹（path 为 "/" 或空）
        parentFolder = m_databaseManager->queryFolderByExactPath("/");
        if (parentFolder.id.isEmpty()) {
            // 如果找不到根文件夹，尝试查找所有文件夹，找到 path 最短的作为根文件夹
            QList<KmsFolder> allFolders = m_databaseManager->queryAllFolders();
            for (const KmsFolder &f : allFolders) {
                if (f.path == "/" || f.path.isEmpty() || (f.path.count('/') == 1 && f.path.startsWith('/'))) {
                    parentFolder = f;
                    break;
                }
            }
        }
    }
    
    if (parentFolder.id.isEmpty()) {
        qDebug() << "FileSystemWatcher: 未找到对应的父文件夹，无法插入目录记录，父文件夹路径:" << parentFolderPath;
        return;
    }
    
    // 找到父文件夹，创建目录记录
    qDebug() << "FileSystemWatcher: 找到父文件夹，ID:" << parentFolder.id << "网盘ID:" << parentFolder.diskId;
    
    // 生成目录ID（使用UUID）
    QString newFolderId = QUuid::createUuid().toString(QUuid::WithoutBraces);
    
    // 创建目录记录
    KmsFolder newFolder;
    newFolder.id = newFolderId;
    newFolder.name = dirName;
    newFolder.diskId = parentFolder.diskId;
    newFolder.folderId = parentFolder.id;
    newFolder.path = folderPath;
    newFolder.creator = QString(); // 本地创建的目录，可能没有创建者信息
    newFolder.creatorId = QString();
    newFolder.type = 0; // 普通文件夹类型
    newFolder.createDate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    newFolder.lastModifyDate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    newFolder.orderNo = 0;
    newFolder.removeOperator = QString();
    newFolder.status = FileSystemStatus::PENDING_ADD; // 本地有新增
    newFolder.version = 0;
    newFolder.maxVersion = 0;
    newFolder.userId = QString(); // 使用当前用户ID（如果需要可以从数据库管理器获取）
    
    // 插入数据库
    if (m_databaseManager->insertFolder(newFolder)) {
        qDebug() << "FileSystemWatcher: 成功插入新目录记录，目录ID:" << newFolderId 
                << "目录名:" << dirName << "状态:3（本地有新增）";
        // 发出文件变更信号，通知系统更新
        emit filesChanged();
    } else {
        qDebug() << "FileSystemWatcher: 插入新目录记录失败，目录名:" << dirName;
    }
}

void KmsFileSystemWatcher::handleFileAddedOrChangedEvent(const QString &path)
{
    // 此方法只处理文件存在的情况（文件删除已在 onFsEvent 中处理）
    qDebug() << "FileSystemWatcher: 处理文件事件（文件存在）:" << path;
    
    // 检查文件是否存在且是文件（不是目录）
    QFileInfo fileInfo(path);
    if (!fileInfo.exists() || !fileInfo.isFile()) {
        qDebug() << "FileSystemWatcher: 文件不存在或不是文件，跳过处理:" << path;
        return;
    }
    
    // 检查是否为 Office 临时文件（文件名以 ~$ 开头）
    QString fileName = fileInfo.fileName();
    if (fileName.startsWith("~$")) {
        qDebug() << "FileSystemWatcher: 检测到 Office 临时文件，跳过处理:" << path;
        return;
    }
    
    // 检查数据库管理器是否可用
    if (!m_databaseManager) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空，无法处理文件事件";
        return;
    }
    
    // 获取相对路径
    QString relativePath = getRelativeFilePath(path);
    if (relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 相对路径为空，无法处理文件事件";
        return;
    }
    
    // 查询 kms_file 表（根据路径匹配）
    KmsFile file = m_databaseManager->queryFileByLocalFilePath(relativePath);
    
    if (file.id.isEmpty()) {
        // 不存在记录，插入 kms_file 记录，设置 status=3（本地有新增）
        qDebug() << "FileSystemWatcher: 检测到新文件创建，准备插入记录:" << path;
        
        // 计算文件校验和
        QString localFileChecksum = calculateFileChecksum(path);
        if (localFileChecksum.isEmpty()) {
            qDebug() << "FileSystemWatcher: 文件校验和计算失败，无法插入新文件记录:" << path;
            return;
        }
        
        // 从相对路径中提取文件夹路径和文件名
        QString normalizedRelativePath = relativePath;
        normalizedRelativePath.replace('\\', '/');
        if (normalizedRelativePath.startsWith('/')) {
            normalizedRelativePath = normalizedRelativePath.mid(1);
        }
        
        int lastSlashIndex = normalizedRelativePath.lastIndexOf('/');
        QString folderPath;
        QString fileName;
        
        if (lastSlashIndex >= 0) {
            folderPath = normalizedRelativePath.left(lastSlashIndex);
            fileName = normalizedRelativePath.mid(lastSlashIndex + 1);
        } else {
            folderPath = QString();
            fileName = normalizedRelativePath;
        }
        
        // 查找文件夹信息
        KmsFolder folder = m_databaseManager->queryFolderByExactPath("/" + folderPath);
        
        if (folder.id.isEmpty()) {
            qDebug() << "FileSystemWatcher: 未找到对应的文件夹，无法插入文件记录，文件夹路径:" << folderPath;
            return;
        }
        
        // 找到文件夹，创建文件记录
        qDebug() << "FileSystemWatcher: 找到文件夹，ID:" << folder.id << "网盘ID:" << folder.diskId;
        
        // 生成文件ID（使用UUID）
        QString newFileId = QUuid::createUuid().toString(QUuid::WithoutBraces);
        
        // 获取文件扩展名
        QString fileExtension = QFileInfo(fileName).suffix().toLower();
        if (!fileExtension.isEmpty()) {
            fileExtension = "." + fileExtension;
        }
        
        // 创建文件记录
        KmsFile newFile;
        newFile.id = newFileId;
        newFile.name = fileName;
        newFile.diskId = folder.diskId;
        newFile.folderId = folder.id;
        newFile.creator = QString(); // 本地创建的文件，可能没有创建者信息
        newFile.creatorId = QString();
        newFile.type = fileExtension;
        newFile.createDate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        newFile.lastModifyDate = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        newFile.originType = 0; // 本地文件
        newFile.originId = QString();
        newFile.size = fileInfo.size();
        newFile.removeOperator = QString();
        newFile.status = FileSystemStatus::PENDING_ADD; // 本地有新增
        newFile.localFileSize = fileInfo.size();
        newFile.localFileChecksum = localFileChecksum;
        newFile.localFilePath = relativePath;
        
        // 插入数据库
        if (m_databaseManager->insertFile(newFile)) {
            qDebug() << "FileSystemWatcher: 成功插入新文件记录，文件ID:" << newFileId 
                    << "文件名:" << fileName << "状态:3（本地有新增）";
            // 发出文件变更信号，通知系统更新
            emit filesChanged();
        } else {
            qDebug() << "FileSystemWatcher: 插入新文件记录失败，文件名:" << fileName;
        }
    } else {
        // 存在记录，计算并更新 local_file_checksum，比较 checksum 和 local_file_checksum
        qDebug() << "FileSystemWatcher: 检测到文件变更，文件ID:" << file.id;
        
        if (FileSystemStatus::isPendingAdd(file.status)) {
            // 新增文件时会执行两次 handleFileAddedOrChangedEvent 事件，当 status == 待提交新增 代表是新插入，不做更新处理
            return;
        }

        // 计算本地文件校验和
        QString localFileChecksum = calculateFileChecksum(path);
        if (localFileChecksum.isEmpty()) {
            qDebug() << "FileSystemWatcher: 文件校验和计算失败，跳过更新:" << path;
            return;
        }
        
        // 更新 local_file_checksum
        qint64 fileSize = fileInfo.size();
        bool updateSuccess = m_databaseManager->updateLocalFileInfo(file.id, fileSize, localFileChecksum, relativePath);
        if (!updateSuccess) {
            qDebug() << "FileSystemWatcher: 更新本地文件信息失败，文件ID:" << file.id;
            return;
        }
        
        qDebug() << "FileSystemWatcher: 成功更新本地文件信息，文件ID:" << file.id 
                 << "本地校验和:" << localFileChecksum;
        
        // 比较 kms_file.checksum（服务器checksum）和 local_file_checksum
        QString serverChecksum = file.checksum;
        if (serverChecksum.isEmpty() || serverChecksum != localFileChecksum) {
            // 不一致时设置 status=待提交变更（本地有变更）
            bool statusUpdateSuccess = m_databaseManager->updateFileStatus(file.id, FileSystemStatus::PENDING_MODIFY);
            if (statusUpdateSuccess) {
                qDebug() << "FileSystemWatcher: 校验和不一致，设置状态为待提交变更，文件ID:" << file.id
                         << "服务器校验和:" << serverChecksum << "本地校验和:" << localFileChecksum;
                emit filesChanged();
            } else {
                qDebug() << "FileSystemWatcher: 更新文件状态失败，文件ID:" << file.id;
            }
        } else {
            // 校验和一致，如果状态不是已同步，则设置为已同步
            if (!FileSystemStatus::isSynced(file.status)) {
                bool statusUpdateSuccess = m_databaseManager->updateFileStatus(file.id, FileSystemStatus::SYNCED);
                if (statusUpdateSuccess) {
                    qDebug() << "FileSystemWatcher: 校验和一致，设置状态为已同步，文件ID:" << file.id;
                    emit filesChanged();
                }
            } else {
                qDebug() << "FileSystemWatcher: 校验和一致，状态已为已同步，无需更新，文件ID:" << file.id;
            }
        }
    }
}

void KmsFileSystemWatcher::handleFileOrDirDeletedEvent(const QString &filePath)
{
    qDebug() << "FileSystemWatcher: handleFileOrDirDeletedEvent 被调用:" << filePath;
    
    // 检查是否在监听目录内
    if (!isFileInWatchedDirectory(filePath)) {
        qDebug() << "FileSystemWatcher: 文件不在监听目录内，忽略删除事件:" << filePath;
        return;
    }
    
    // 获取相对路径
    QString relativePath = getRelativeFilePath(filePath);
    if (relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 相对路径为空，无法处理文件删除:" << filePath;
        return;
    }
    
    qDebug() << "FileSystemWatcher: 文件删除，相对路径:" << relativePath;
    
    // 检查数据库管理器是否可用
    if (!m_databaseManager) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空，无法处理文件删除";
        return;
    }
    
    // 查询 kms_file 表（根据路径匹配）
    KmsFile file = m_databaseManager->queryFileByLocalFilePath(relativePath);

    if (!file.id.isEmpty()) {
        // 存在记录，检查状态
        qDebug() << "FileSystemWatcher: 文件删除，找到数据库记录，文件ID:" << file.id 
                << "当前状态:" << file.status;
        
        // 如果状态为 待下载，不做处理（文件还未下载，删除本地文件不影响）
        if (FileSystemStatus::isPendingDownload(file.status)) {
            qDebug() << "FileSystemWatcher: 文件状态为待下载，不做处理，文件ID:" << file.id;
            return;
        }
        
        // 如果状态为 待提交新增，则直接删除记录
        if (FileSystemStatus::isPendingAdd(file.status)) {
            bool deleted = m_databaseManager->deleteFile(file.id);
            if (deleted) {
                qDebug() << "FileSystemWatcher: 成功删除待提交新增的文件记录，文件ID:" << file.id;
                // 发出文件变更信号，通知系统更新
                emit filesChanged();
            } else {
                qDebug() << "FileSystemWatcher: 删除文件记录失败，文件ID:" << file.id;
            }
            return;
        }
        
        // 其他状态，设置 status = 待提交删除
        bool success = m_databaseManager->updateFileStatus(file.id, FileSystemStatus::PENDING_DELETE);
        if (success) {
            qDebug() << "FileSystemWatcher: 成功设置文件状态为待提交删除，文件ID:" << file.id;
            // 发出文件变更信号，通知系统更新
            emit filesChanged();
        } else {
            qDebug() << "FileSystemWatcher: 设置文件状态失败，文件ID:" << file.id;
        }
        return;
    }

    // 查询 kms_folder 表（根据路径匹配）
    KmsFolder folder = m_databaseManager->queryFolderByExactPath("/" + relativePath);

    if (!folder.id.isEmpty()) {
        // 存在记录，检查状态
        qDebug() << "FileSystemWatcher: 文件夹删除，找到数据库记录，文件夹ID:" << folder.id 
                 << "当前状态:" << folder.status;
        
        // 如果状态为 待提交新增，则直接删除记录（需要递归删除子文件）
        if (FileSystemStatus::isPendingAdd(folder.status)) {
            bool deleted = m_databaseManager->deleteFolder(folder.id);
            if (deleted) {
                qDebug() << "FileSystemWatcher: 成功删除待提交新增的文件夹记录，文件夹ID:" << folder.id;
                // 发出文件夹变更信号，通知系统更新
                emit filesChanged();
            } else {
                qDebug() << "FileSystemWatcher: 删除文件夹记录失败，文件夹ID:" << folder.id;
            }
            return;
        }
        
        // 其他状态，设置 status = 待提交删除
        bool success = m_databaseManager->updateFolderStatus(folder.id, FileSystemStatus::PENDING_DELETE);
        if (success) {
            qDebug() << "FileSystemWatcher: 成功设置文件夹状态为 -1（待提交删除），文件夹ID:" << folder.id;
            // 发出文件夹变更信号，通知系统更新
            emit filesChanged();
        } else {
            qDebug() << "FileSystemWatcher: 设置文件夹状态失败，文件夹ID:" << folder.id;
        }
        return;
    }

    // 不存在记录，不做处理
    qDebug() << "FileSystemWatcher: 文件 或 文件夹 删除，但数据库中不存在记录，不做处理，相对路径:" << relativePath;
}


void KmsFileSystemWatcher::startDelayTimer()
{
    // 如果定时器未运行，则启动它
    if (!m_delayTimer->isActive()) {
        m_delayTimer->start();
    }
}

void KmsFileSystemWatcher::processDelayedFsActions()
{
    QList<FsAction> actionsToProcess;
    
    // 使用互斥锁保护，复制待处理的动作列表
    {
        QMutexLocker locker(&m_pendingActionsMutex);
        qDebug() << "FileSystemWatcher: 开始处理延迟变更，待处理文件数量:" << m_pendingActions.size();

        if (m_pendingActions.isEmpty()) {
            qDebug() << "FileSystemWatcher: 没有待处理的文件变更";
            return;
        }
        
        // 复制列表以便在锁外处理
        actionsToProcess = m_pendingActions;
        m_pendingActions.clear();
    }

    for (const FsAction &action : actionsToProcess) {
        if (!action.path) {
            continue;
        }

        QString filePath = *action.path;
        qDebug() << "FileSystemWatcher: 处理文件变更，事件类型:" << static_cast<int>(action.eventType) << "路径:" << filePath;

        if (!m_databaseManager) {
            continue;
        }

        // 根据事件类型进行不同处理
        if (action.eventType == FsEventType::FileOrDirDeleted) {
            // 文件删除事件，调用删除处理函数
            handleFileOrDirDeletedEvent(filePath);
            continue;
        }

        if (action.eventType == FsEventType::DirAdded) {
            // 目录新增事件，暂时跳过（目录处理逻辑可能需要单独实现）
            handleDirAddedEvent(filePath);
            continue;
        }

        if (action.eventType == FsEventType::FileAdded) {
            // 文件新增事件，调用创建或变更处理函数
            // 文件新增 会同时触发 新增 和 文件变更，因此这里屏蔽
            // handleFileAddedOrChangedEvent(filePath);
            continue;
        }

        if (action.eventType == FsEventType::FileModified) {
            // 文件修改事件，调用文件修改处理函数
            handleFileAddedOrChangedEvent(filePath);
            continue;
        }
    }

    // 清理内存：删除所有 path 指针指向的 QString 对象
    for (FsAction &action : actionsToProcess) {
        if (action.path) {
            delete action.path;
            action.path = nullptr;
        }
    }

    qDebug() << "FileSystemWatcher: 完成处理所有延迟变更";

    // if (anyChanged) {
    //     emit filesChanged();
    // }
}

QString KmsFileSystemWatcher::calculateFileChecksum(const QString &filePath)
{
    qDebug() << "FileSystemWatcher: 开始计算文件校验和:" << filePath;
    
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "FileSystemWatcher: 无法打开文件计算校验和:" << filePath << "错误:" << file.errorString();
        return QString();
    }

    qDebug() << "FileSystemWatcher: 文件打开成功，开始计算SHA-1校验和:" << filePath;
    
    QCryptographicHash hash(QCryptographicHash::Sha1);
    if (hash.addData(&file)) {
        QString checksum = hash.result().toHex();
        qDebug() << "FileSystemWatcher: 文件校验和计算成功:" << filePath << "->" << checksum;
        return checksum;
    }

    qDebug() << "FileSystemWatcher: 文件校验和计算失败:" << filePath;
    return QString();
}

void KmsFileSystemWatcher::updateFileInfoInDatabase(const QString &filePath)
{
    qDebug() << "FileSystemWatcher: 开始更新数据库文件信息:" << filePath;
    
    if (!m_databaseManager) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空，无法更新文件信息";
        return;
    }

    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists() || !fileInfo.isFile()) {
        qDebug() << "FileSystemWatcher: 文件不存在或不是文件:" << filePath;
        return;
    }

    qDebug() << "FileSystemWatcher: 文件信息检查通过，文件大小:" << fileInfo.size() << "字节";

    // 获取相对路径
    QString relativePath = getRelativeFilePath(filePath);
    if (relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 无法获取相对路径:" << filePath;
        return;
    }

    qDebug() << "FileSystemWatcher: 获取到相对路径:" << relativePath;

    // 查找对应的文件ID
    QString fileId = findFileIdByRelativePath(relativePath);
    if (fileId.isEmpty()) {
        qDebug() << "FileSystemWatcher: 未找到对应的文件ID，相对路径:" << relativePath;
        return;
    }

    qDebug() << "FileSystemWatcher: 找到对应的文件ID:" << fileId;

    // 获取文件大小
    qint64 fileSize = fileInfo.size();
    qDebug() << "FileSystemWatcher: 文件大小:" << fileSize << "字节";

    // 计算文件校验和
    QString checksum = calculateFileChecksum(filePath);
    if (checksum.isEmpty()) {
        qDebug() << "FileSystemWatcher: 校验和计算失败，跳过数据库更新";
        return;
    }

    qDebug() << "FileSystemWatcher: 准备更新数据库，文件ID:" << fileId << "大小:" << fileSize << "校验和:" << checksum;

    // 更新数据库
    bool success = m_databaseManager->updateLocalFileInfo(fileId, fileSize, checksum);
    if (success) {
        qDebug() << "FileSystemWatcher: 数据库更新成功，文件ID:" << fileId 
                 << "大小:" << fileSize << "校验和:" << checksum;
    } else {
        qDebug() << "FileSystemWatcher: 数据库更新失败，文件ID:" << fileId;
    }
}

QString KmsFileSystemWatcher::getRelativeFilePath(const QString &filePath) const
{
    if (m_watchedDirectory.isEmpty()) {
        return QString();
    }

    QString cleanFilePath = QDir::cleanPath(filePath);
    QString cleanWatchedDir = QDir::cleanPath(m_watchedDirectory);

    if (!cleanFilePath.startsWith(cleanWatchedDir)) {
        return QString();
    }

    // 获取相对路径，去掉开头的斜杠
    QString relativePath = cleanFilePath.mid(cleanWatchedDir.length());
    if (relativePath.startsWith('/')) {
        relativePath = relativePath.mid(1);
    }

    return relativePath;
}

QString KmsFileSystemWatcher::findFileIdByRelativePath(const QString &relativePath) const
{
    qDebug() << "FileSystemWatcher: 查找文件ID，相对路径:" << relativePath;
    
    if (!m_databaseManager || relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空或相对路径为空";
        return QString();
    }

    // 规范化相对路径（统一使用正斜杠，去掉开头的斜杠）
    QString normalizedRelativePath = relativePath;
    normalizedRelativePath.replace('\\', '/');
    if (normalizedRelativePath.startsWith('/')) {
        normalizedRelativePath = normalizedRelativePath.mid(1);
    }

    // 从相对路径中提取文件夹路径和文件名
    int lastSlashIndex = normalizedRelativePath.lastIndexOf('/');
    QString folderPath;
    QString fileName;
    
    if (lastSlashIndex >= 0) {
        // 有文件夹路径
        folderPath = normalizedRelativePath.left(lastSlashIndex);
        fileName = normalizedRelativePath.mid(lastSlashIndex + 1);
    } else {
        // 文件直接在根目录下
        folderPath = QString();
        fileName = normalizedRelativePath;
    }
    
    qDebug() << "FileSystemWatcher: 提取的文件夹路径:" << folderPath 
             << "文件名:" << fileName;

    // 步骤1: 通过 kms_folder.path == 路径 查出 folderId
    KmsFolder folder = m_databaseManager->queryFolderByExactPath("/" + folderPath);
    if (folder.id.isEmpty()) {
        qDebug() << "FileSystemWatcher: 未找到匹配的文件夹，路径:" << folderPath;
        return QString();
    }
    
    QString folderId = folder.id;
    qDebug() << "FileSystemWatcher: 找到文件夹，ID:" << folderId 
             << "路径:" << folder.path;

    // 步骤2: 通过 kms_file.folder_id == folder_id 获得 fileId
    QList<KmsFile> files = m_databaseManager->queryFilesByFolderId(folderId);
    qDebug() << "FileSystemWatcher: 文件夹下的文件数量:" << files.size();
    
    for (const auto &file : files) {
        // 比较文件名
        if (file.name == fileName) {
            qDebug() << "FileSystemWatcher: 找到匹配的文件，ID:" << file.id 
                     << "文件名:" << file.name 
                     << "文件夹路径:" << folder.path;
            return file.id;
        }
    }

    qDebug() << "FileSystemWatcher: 未找到匹配的文件，相对路径:" << relativePath;
    return QString();
}

QString KmsFileSystemWatcher::findFileIdByLocalFilePath(const QString &relativePath) const
{
    qDebug() << "FileSystemWatcher: 通过 local_file_path 查找文件ID，相对路径:" << relativePath;
    
    if (!m_databaseManager || relativePath.isEmpty()) {
        qDebug() << "FileSystemWatcher: 数据库管理器为空或相对路径为空";
        return QString();
    }

    // 规范化相对路径（统一使用正斜杠，去掉开头的斜杠）
    QString normalizedRelativePath = relativePath;
    normalizedRelativePath.replace('\\', '/');
    if (normalizedRelativePath.startsWith('/')) {
        normalizedRelativePath = normalizedRelativePath.mid(1);
    }

    // 通过 local_file_path 字段查找文件
    KmsFile file = m_databaseManager->queryFileByLocalFilePath(normalizedRelativePath);
    
    if (!file.id.isEmpty()) {
        qDebug() << "FileSystemWatcher: 通过 local_file_path 找到匹配的文件，ID:" << file.id 
                 << "本地路径:" << file.localFilePath;
        return file.id;
    }

    qDebug() << "FileSystemWatcher: 通过 local_file_path 未找到匹配的文件，相对路径:" << normalizedRelativePath;
    return QString();
}

// libuv 相关方法实现

void KmsFileSystemWatcher::startEventLoop()
{
    if (m_loop) {
        qDebug() << "FileSystemWatcher: 事件循环已存在";
        return;
    }

    qDebug() << "FileSystemWatcher: 创建 libuv 事件循环";
    m_loop = new uv_loop_t;
    if (uv_loop_init(m_loop) != 0) {
        qDebug() << "FileSystemWatcher: 初始化事件循环失败";
        delete m_loop;
        m_loop = nullptr;
        return;
    }

    // 创建线程运行事件循环
    m_eventLoopThread = QThread::create([this]() {
        this->runEventLoop();
    });
    m_eventLoopThread->start();

    qDebug() << "FileSystemWatcher: libuv 事件循环线程已启动";
}

void KmsFileSystemWatcher::stopEventLoop()
{
    if (!m_loop) {
        return;
    }

    qDebug() << "FileSystemWatcher: 停止 libuv 事件循环";
    m_stopping = true;

    // 先移除所有监听器（这会关闭所有句柄）
    removeAllWatchers();

    // 等待线程结束（让 libuv 线程处理所有关闭回调）
    if (m_eventLoopThread && m_eventLoopThread->isRunning()) {
        // 停止事件循环（让线程自然退出）
        uv_stop(m_loop);
        
        // 等待线程结束（这会确保线程中的事件循环处理所有关闭回调）
        m_eventLoopThread->wait(5000); // 最多等待5秒
        
        if (m_eventLoopThread->isRunning()) {
            qDebug() << "FileSystemWatcher: 警告：事件循环线程未在5秒内结束";
        }
        
        delete m_eventLoopThread;
        m_eventLoopThread = nullptr;
    }

    // 在主线程中运行事件循环以处理剩余的关闭回调（如果还有）
    // 使用 UV_RUN_DEFAULT 模式，处理完所有事件后返回
    int loopAlive = uv_loop_alive(m_loop);
    if (loopAlive) {
        qDebug() << "FileSystemWatcher: 事件循环仍有活动句柄，运行以处理关闭回调";
        // 运行事件循环直到没有活动句柄
        while (uv_loop_alive(m_loop)) {
            uv_run(m_loop, UV_RUN_ONCE);
            // 避免无限循环
            QThread::msleep(10);
        }
    }

    // 关闭事件循环（此时应该没有活动的句柄了）
    int result = uv_loop_close(m_loop);
    if (result != 0) {
        qDebug() << "FileSystemWatcher: 关闭事件循环警告，返回值:" << result << uv_strerror(result);
        // 如果还有活动句柄，强制清理
        if (result == UV_EBUSY) {
            qDebug() << "FileSystemWatcher: 事件循环仍有活动句柄，可能无法完全关闭";
        }
    }
    
    delete m_loop;
    m_loop = nullptr;

    qDebug() << "FileSystemWatcher: libuv 事件循环已停止";
}

void KmsFileSystemWatcher::runEventLoop()
{
    qDebug() << "FileSystemWatcher: 事件循环线程开始运行";
    while (!m_stopping && m_loop) {
        uv_run(m_loop, UV_RUN_ONCE);
        QThread::msleep(10); // 避免CPU占用过高
    }
    qDebug() << "FileSystemWatcher: 事件循环线程结束";
}

bool KmsFileSystemWatcher::addWatcher(const QString &path, bool isDirectory)
{
    if (!m_loop) {
        qDebug() << "FileSystemWatcher: 事件循环未启动，无法添加监听";
        return false;
    }

    QString cleanPath = QDir::cleanPath(path);
    
    // 检查是否已存在
    {
        QMutexLocker locker(&m_watchersMutex);
        if (m_watchers.contains(cleanPath)) {
            qDebug() << "FileSystemWatcher: 路径已在监听中:" << cleanPath;
            return true;
        }
    }

    // 创建 WatcherInfo
    WatcherInfo *info = new WatcherInfo;
    info->watcher = this;
    info->path = cleanPath;
    info->isDirectory = isDirectory;
    info->handle = new uv_fs_event_t;

    // 初始化 handle
    int r = uv_fs_event_init(m_loop, info->handle);
    if (r != 0) {
        qDebug() << "FileSystemWatcher: 初始化 fs_event 失败:" << uv_strerror(r);
        delete info->handle;
        delete info;
        return false;
    }

    // 设置数据指针
    info->handle->data = info;

    // 转换为 UTF-8 字节数组（Windows 上需要）
    QByteArray pathBytes = cleanPath.toUtf8();
    const char *pathStr = pathBytes.constData();

    // 启动监听
    // 在所有平台上，对目录使用递归标志，可以监听整个目录树
    unsigned int flags = 0;
    if (isDirectory) {
        flags = UV_FS_EVENT_RECURSIVE;
        qDebug() << "FileSystemWatcher: 使用递归标志监听目录:" << cleanPath;
    }
    
    r = uv_fs_event_start(info->handle, onFsEvent, pathStr, flags);
    if (r != 0) {
        qDebug() << "FileSystemWatcher: 启动 fs_event 失败:" << uv_strerror(r) << "路径:" << cleanPath;
        delete info->handle;
        delete info;
        return false;
    }

    // 添加到映射
    {
        QMutexLocker locker(&m_watchersMutex);
        m_watchers[cleanPath] = info;
    }

    qDebug() << "FileSystemWatcher: 成功添加监听:" << cleanPath << (isDirectory ? "(目录)" : "(文件)");
    return true;
}

void KmsFileSystemWatcher::removeWatcher(const QString &path)
{
    QString cleanPath = QDir::cleanPath(path);
    
    WatcherInfo *info = nullptr;
    {
        QMutexLocker locker(&m_watchersMutex);
        if (m_watchers.contains(cleanPath)) {
            info = m_watchers.take(cleanPath);
        }
    }

    if (info) {
        if (info->handle && m_loop && !info->closing) {
            info->closing = true;
            uv_fs_event_stop(info->handle);
            // 清除句柄的 data 指针，避免关闭回调访问已删除的 WatcherInfo
            info->handle->data = nullptr;
            // 关闭句柄（异步，回调函数会删除句柄）
            uv_close(reinterpret_cast<uv_handle_t*>(info->handle), onHandleClose);
            info->handle = nullptr;
        }
        delete info;
        qDebug() << "FileSystemWatcher: 成功移除监听:" << cleanPath;
    }
}

void KmsFileSystemWatcher::removeAllWatchers()
{
    QList<WatcherInfo*> watchers;
    {
        QMutexLocker locker(&m_watchersMutex);
        watchers = m_watchers.values();
        m_watchers.clear();
    }

    for (WatcherInfo *info : watchers) {
        if (info->handle && m_loop && !info->closing) {
            info->closing = true;
            uv_fs_event_stop(info->handle);
            // 清除句柄的 data 指针，避免关闭回调访问已删除的 WatcherInfo
            info->handle->data = nullptr;
            // 关闭句柄（异步，回调函数会删除句柄）
            uv_close(reinterpret_cast<uv_handle_t*>(info->handle), onHandleClose);
            info->handle = nullptr;
        }
        delete info;
    }

    qDebug() << "FileSystemWatcher: 已移除所有监听器";
}

void KmsFileSystemWatcher::onFsEvent(uv_fs_event_t *handle, const char *filename, int events, int status)
{
    WatcherInfo *info = static_cast<WatcherInfo*>(handle->data);
    if (!info || !info->watcher || info->closing) {
        // 如果 WatcherInfo 无效或正在关闭，忽略事件
        return;
    }

    if (status != 0) {
        qDebug() << "FileSystemWatcher: fs_event 错误:" << uv_strerror(status);
        return;
    }

    // 如果没有文件名，忽略事件（只处理子文件/目录的变化）
    if (!filename || strlen(filename) == 0) {
        return;
    }

    QString path = info->path;
    
    // 构建完整路径
    QString fullPath = path;
    if (!path.endsWith('/') && !path.endsWith('\\')) {
        fullPath += "/";
    }
    fullPath += QString::fromUtf8(filename);

    // 判断事件类型
    bool isRename = (events & UV_RENAME) != 0;
    bool isChange = (events & UV_CHANGE) != 0;

    // 检查路径是否存在
    QFileInfo fullPathInfo(fullPath);
    bool pathExists = fullPathInfo.exists();
    bool isDir = pathExists ? fullPathInfo.isDir() : false;
    bool isFile = pathExists ? fullPathInfo.isFile() : false;

    // 判断事件类型
    FsEventType eventType;

    if (isRename) {
        // RENAME 事件：可能是新增、删除或重命名
        // 注意：在 libuv 中，RENAME 事件在以下情况会触发：
        // 1. 文件/目录重命名（会触发两次：旧路径和新路径）
        // 2. 文件/目录新增（某些平台，路径存在）
        // 3. 文件/目录删除（某些平台，路径不存在）
        // 
        // 处理策略：
        // - 对于路径存在的情况，可能是新增或重命名（新路径）
        // - 对于路径不存在的情况，可能是删除或重命名（旧路径）
        // - 重命名操作会同时触发旧路径（不存在）和新路径（存在）的 RENAME 事件
        // - 要准确检测重命名，需要跟踪事件序列（短时间内删除+新增）
        // 
        // 简化处理策略：
        // - 如果路径存在，优先视为新增（因为新增更常见）
        // - 如果路径不存在，优先视为删除（因为删除更常见）
        // - 重命名事件的准确检测需要额外的跟踪逻辑
        // - 注意：这可能导致某些重命名操作被误判为新增/删除
        if (pathExists) {
            // 路径存在，可能是新增或重命名（新路径）
            // 简化处理：优先视为新增
            if (isDir) {
                eventType = FsEventType::DirAdded;
            } else {
                eventType = FsEventType::FileAdded;
            }
        } else {
            // 路径不存在，可能是删除或重命名（旧路径）
            // 简化处理：优先视为删除
            eventType = FsEventType::FileOrDirDeleted;
        }
    } else if (isChange) {
        // CHANGE 事件：内容变更（仅文件）
        if (isDir) {
            // 目录的 CHANGE 事件通常表示目录内容变化，这里不处理
            return;
        } else if (isFile) {
            eventType = FsEventType::FileModified;
        } else {
            // 路径不存在，可能是删除操作
            eventType = FsEventType::FileOrDirDeleted;
        }
    } else {
        // 未知事件类型，忽略
        return;
    }

    // 使用 switch 输出事件信息（仅保留需要的事件类型）
    switch (eventType) {
        case FsEventType::FileAdded:
            qDebug() << "文件新增: " << fullPath;
            break;
        case FsEventType::FileModified:
            qDebug() << "文件内容变更: " << fullPath;
            break;
        case FsEventType::FileOrDirDeleted:
            // 合并文件删除和目录删除为一个事件
            qDebug() << "文件或目录删除: " << fullPath;
            break;
        case FsEventType::DirAdded:
            qDebug() << "目录新增: " << fullPath;
            break;
        default:
            // 其他事件类型忽略
            break;
    }

    // 创建 FsAction 并添加到延迟处理队列
    FsAction action;
    action.eventType = eventType;
    action.path = new QString(fullPath);  // 分配新的 QString 对象
    
    // 使用互斥锁保护，添加到待处理队列
    {
        QMutexLocker locker(&info->watcher->m_pendingActionsMutex);
        info->watcher->m_pendingActions.append(action);
    }
    
    // 使用 QMetaObject::invokeMethod 安全地从 libuv 线程启动定时器
    QMetaObject::invokeMethod(info->watcher, "startDelayTimer", Qt::QueuedConnection);
}
